/* 缓存贴图加载器：THREE.TextureLoader 的增强版
 *
 * 增强功能
 *  - 带缓存
 *  - 封装颜色空间
 */
import * as THREE from 'three'

export class CachedTextureLoader {
  // 原生材质加载器
  #textureLoader = new THREE.TextureLoader()

  // 加载SRGB：漫反射、自发光
  #srgbCache: { [url: string]: THREE.Texture } = {} // 缓存
  // 同步版
  loadSrgbSync(map?: string, flipY = false): THREE.Texture | null {
    if (!map) return null

    if (this.#srgbCache[map]) {
      return this.#srgbCache[map]
    } else {
      const texture = this.#textureLoader.load(map)
      texture.anisotropy = 4
      texture.flipY = flipY
      texture.colorSpace = THREE.SRGBColorSpace // 设置颜色空间
      this.#srgbCache[map] = texture
      return texture
    }
  }
  // 异步版
  async loadSrgbAsync(map?: string, flipY = false): Promise<THREE.Texture | null> {
    if (!map) return null

    if (this.#srgbCache[map]) {
      return this.#srgbCache[map]
    } else {
      const texture = await this.#textureLoader.loadAsync(map)
      texture.anisotropy = 4
      texture.flipY = flipY
      texture.colorSpace = THREE.SRGBColorSpace // 设置颜色空间
      this.#srgbCache[map] = texture
      return texture
    }
  }

  // 加载线性：法线、粗糙度、金属度、AO
  // 说明：AO 本来应该用 srgb 处理，但由于本系统中将粗糙度、金属度和 AO 打包为单个 ARM 贴图了
  // 所以采取影响最小的 AO 改 Linear 的方案
  #linearCache: { [url: string]: THREE.Texture } = {} // 缓存
  // 同步版
  loadLinearSync(map?: string, flipY = false): THREE.Texture | null {
    if (!map) return null

    if (this.#linearCache[map]) {
      return this.#linearCache[map]
    } else {
      const texture = this.#textureLoader.load(map)
      texture.anisotropy = 4
      texture.flipY = flipY
      texture.colorSpace = THREE.LinearSRGBColorSpace // 设置颜色空间
      this.#linearCache[map] = texture
      return texture
    }
  }
  // 异步版
  async loadLinearAsync(map?: string, flipY = false): Promise<THREE.Texture | null> {
    if (!map) return null

    if (this.#linearCache[map]) {
      return this.#linearCache[map]
    } else {
      const texture = await this.#textureLoader.loadAsync(map)
      texture.anisotropy = 4
      texture.flipY = flipY
      texture.colorSpace = THREE.LinearSRGBColorSpace // 设置颜色空间
      this.#linearCache[map] = texture
      return texture
    }
  }

  // 加载环境贴图（仅提供同步版）
  #envCache: { [url: string]: THREE.Texture } = {} // 缓存
  loadEnvSync(map?: string): THREE.Texture | null {
    if (!map) return null

    if (this.#envCache[map]) {
      return this.#envCache[map]
    } else {
      const texture = this.#textureLoader.load(map)
      texture.anisotropy = 4
      texture.colorSpace = THREE.SRGBColorSpace
      texture.mapping = THREE.EquirectangularReflectionMapping
      this.#envCache[map] = texture
      return texture
    }
  }
}

/** 带缓存的纹理加载器的默认实例 */
export const cachedTextureLoader = new CachedTextureLoader()
